import json
import logging
import os
import threading
import time

from django.db.models import Sum, Max
from django.forms.models import model_to_dict
from django.http import JsonResponse, FileResponse
from django.shortcuts import HttpResponse, redirect
from django.urls import reverse
from django.utils.encoding import escape_uri_path
from django.views.decorators.http import require_POST

from DataPlatform.settings import STATIC_ROOT
from business.models import ICE, GasBoiler, ElectricBoiler, AR, IceTank, ERU, AirPump, GroundPump, GasTurbine, \
    WindPower, PVP, ARS, Buttery, CalResult, DesignPlan, EconomicParams, OptResult, OptConfig, ConfigLimit
from users.tools import auth
from users.tools.auth import decode_token, get_account
from users.tools.response import RspMsg
from . import helper
from .calculate import CalThread
from .helper import save_params, page_n
from .opt_cal import OptThread
from pandas import DataFrame

logger = logging.getLogger('stu')


def get_params_file(request):
    """
    用于获取计算配置文件的方法，通过get方法中的参数判断获取的是哪一种excel文件
    如果判断正确，则浏览器会直接进行下载，否则会返回请求数据错误
    :param request:
    :return:
    """
    which = request.GET.get('which', '')
    if which == 'load':
        path = 'data_target.xlsx'
        file_name = '全年负载及相关费率'
    elif which == 'wind':
        path = 'wind.xlsx'
        file_name = '风力发电数据'
    elif which == 'light':
        path = 'light.xlsx'
        file_name = '光伏发电数据'
    elif which == 'opt_load':
        path = 'opt_load.xlsx'
        file_name = '优化负载文件'
    else:
        return HttpResponse('请求数据错误')

    rsp = FileResponse(open(STATIC_ROOT + '/business/params_file/' + path, 'rb'))
    rsp['Content-Disposition'] = "attachment; filename*=utf-8''{}".format(escape_uri_path(file_name + '.xlsx'))
    return rsp


# 记录所有规划子线程的字典类型（全局）
cal_dict = {}

# 记录所有优化子线程的字典类型（全局）
opt_dict = {}


# ------------------------------------------------
# 保存经评数据
@require_POST
def save_eco_params(request):
    rsp = RspMsg()
    try:
        target = EconomicParams(**request.ask['ecoParams'])
        target.id = 1
        target.save()
    except Exception as e:
        logger.exception("存储失败，请联系管理员")
        rsp.error(500, '存储失败，请联系管理员')
    return JsonResponse(rsp.get_result())


# 获取经评数据
@require_POST
def get_eco_params(request):
    rsp = RspMsg()
    data = EconomicParams.objects.values("capital_ratio", "loan_ratio", "lending_rates", "liquidity_ratio",
                                         "depreciation_period", "residual_rate", "reserve_rate", "e_vat", "hc_vat",
                                         "cgccf", "cgcepf", "cgcief", "cgcof", "scesf", "apia").first()
    rsp.data = {"eco_params": data}
    return JsonResponse(rsp.get_result())


# 获取历史规划数据
@require_POST
def show_his_params(request):
    """
    返回历史配置信息的列表
    """
    current_page = request.ask['currentPage']  # 当前页数
    current_size = request.ask['currentSize']  # 当前每页个数
    search_text = request.ask['searchText']  # 待查询的关键字
    token = request.ask['token']
    status, payload = decode_token(token)
    account = get_account(payload)
    from business.helper import page_n
    designs = DesignPlan.objects \
        .filter(belongs__account=account, d_name__contains=search_text) \
        .values('d_name', 'd_desc', 'time', 'design_id', 'wind_is_selected', 'solar_is_selected').order_by('-time')
    rsp = RspMsg()
    data = page_n(designs, current_page, current_size)

    req_users = list(data.object_list)
    rsp.data = {
        'plans': req_users,
        'currentPage': current_page,
        'currentSize': current_size,
        'totalCount': designs.count()
    }
    return JsonResponse(rsp.get_result())


# 获取文件接口
def get_his_file(request):
    """
    获取计算历史数据，包括：负载文件，风力参数，光伏参数，经济评价参数以及计算结果
    获取方式为：通过用户账号，文件类型以及计算唯一识别码进行组合后，即可获取到历史文件
    :param request:
    :return:
    """
    who = request.GET.get('who', '')
    catalog = request.GET.get('catalog', '')
    mark = request.GET.get('mark', '')

    if catalog == 'load':
        file_name = '全年负载及相关费率'
    elif catalog == 'wind':
        file_name = '风力发电数据'
    elif catalog == 'light':
        file_name = '光伏发电数据'
    elif catalog == 'economic':
        file_name = '经评数据'
    elif catalog == 'result':
        file_name = '计算结果'
    else:
        file_name = ''

    if who and file_name:
        target_file_path = os.path.join(STATIC_ROOT + '/business/user_params_file/', who + "_" + catalog + "_" + mark)
        rsp = FileResponse(open(target_file_path + '.xlsx', 'rb'))
        rsp['Content-Disposition'] = "attachment; filename*=utf-8''{}".format(escape_uri_path(file_name + '.xlsx'))
        rsp['Content-Type'] = "text/html;charset=UTF-8"
        return rsp
    else:
        return HttpResponse("目标文件缺失，请联系管理员")


# 展示所有计算配置
@require_POST
def show_cal_params(request):
    """
    根据用户的账号和get中传入的具体某次规划的id进行查看具体计算的配置信息
    :param request:
    :return:
    """
    who = request.ask['who']
    which = request.ask['which']

    cal_data = CalResult.objects.filter(design_id=which).aggregate(ele_buy=Max('ele_buy'), gas_buy=Max('gas_buy'),
                                                                   heat_buy=Max('heat_buy'),
                                                                   wind_power=Max('wind_power'),
                                                                   pvp_power=Max('pvp_power'),
                                                                   ele_dis=Max('ele_dis'),
                                                                   cchp_oh=Max('cchp_oh'), ice_os=Max('ice_os'),
                                                                   cchp_oc=Max('cchp_oc'), gp_oh=Max('gp_oh'),
                                                                   heat_dis=Max('heat_release'),
                                                                   gp_oc=Max('gp_oc'),
                                                                   ap_oc=Max('ap_oc'), gb_oh=Max('gb_oh'),
                                                                   ar_oc=Max('ar_oc'),
                                                                   eb_oh=Max('eb_oh'), eru=Max('eru_oc'),
                                                                   it_dis=Max('it_dis'), ice_soc=Max('ice_soc'),
                                                                   ap_oh=Max('ap_oh'),
                                                                   ar_oh=Max('ar_oh'),
                                                                   heat_soc=Max('heat_soc'), ele_soc=Max('ele_soc'))
    for (k, v) in cal_data.items():
        if v is None:
            cal_data[k] = 0
    ele_sum = cal_data['ice_os'] + cal_data['ele_buy'] + cal_data['wind_power'] + cal_data['pvp_power'] + cal_data[
        'ele_dis']
    heat_sum = cal_data['cchp_oh'] + cal_data['gb_oh'] + cal_data['gp_oh'] + cal_data['eb_oh'] + cal_data['heat_buy'] + \
               cal_data['heat_dis']
    cold_sum = cal_data['cchp_oc'] + cal_data['gp_oc'] + cal_data['ap_oc'] + cal_data['ar_oc'] + cal_data['it_dis'] + \
               cal_data['eru']

    if not ele_sum == 0:
        cal_data['ice_os_p'] = cal_data['ice_os'] / ele_sum * 100
        cal_data['ele_buy_p'] = cal_data['ele_buy'] / ele_sum * 100
        cal_data['wind_power_p'] = cal_data['wind_power'] / ele_sum * 100
        cal_data['pvp_power_p'] = cal_data['pvp_power'] / ele_sum * 100
        cal_data['ele_dis_p'] = cal_data['ele_dis'] / ele_sum * 100
    else:
        cal_data['ice_os_p'] = 0
        cal_data['ele_buy_p'] = 0
        cal_data['wind_power_p'] = 0
        cal_data['pvp_power_p'] = 0
        cal_data['ele_dis_p'] = 0

    if not heat_sum == 0:
        cal_data['cchp_oh_p'] = cal_data['cchp_oh'] / heat_sum * 100
        cal_data['gb_oh_p'] = cal_data['gb_oh'] / heat_sum * 100
        cal_data['gp_oh_p'] = cal_data['gp_oh'] / heat_sum * 100
        cal_data['eb_oh_p'] = cal_data['eb_oh'] / heat_sum * 100
        cal_data['heat_buy_p'] = cal_data['heat_buy'] / heat_sum * 100
        cal_data['heat_dis_p'] = cal_data['heat_dis'] / heat_sum * 100
        cal_data['ap_oh_p'] = cal_data['ap_oh'] / heat_sum * 100
        cal_data['ar_oh_p'] = cal_data['ar_oh'] / heat_sum * 100
    else:
        cal_data['cchp_oh_p'] = 0
        cal_data['gb_oh_p'] = 0
        cal_data['gp_oh_p'] = 0
        cal_data['eb_oh_p'] = 0
        cal_data['heat_buy_p'] = 0
        cal_data['heat_dis_p'] = 0
        cal_data['ap_oh_p'] = 0
        cal_data['ar_oh_p'] = 0

    if not cold_sum == 0:
        cal_data['cchp_oc_p'] = cal_data['cchp_oc'] / cold_sum * 100
        cal_data['gp_oc_p'] = cal_data['gp_oc'] / cold_sum * 100
        cal_data['ap_oc_p'] = cal_data['ap_oc'] / cold_sum * 100
        cal_data['ar_oc_p'] = cal_data['ar_oc'] / cold_sum * 100
        cal_data['it_dis_p'] = cal_data['it_dis'] / cold_sum * 100
        cal_data['eru_p'] = cal_data['eru'] / cold_sum * 100
    else:
        cal_data['cchp_oc_p'] = 0
        cal_data['gp_oc_p'] = 0
        cal_data['ap_oc_p'] = 0
        cal_data['ar_oc_p'] = 0
        cal_data['it_dis_p'] = 0
        cal_data['eru_p'] = 0

    rsp = RspMsg()
    rsp.data = {"params": model_to_dict(DesignPlan.objects.get(design_id=which, belongs__account=who)),
                "cal_data": cal_data}
    return JsonResponse(rsp.get_result())


# 删除历史规划信息
@require_POST
def delete_his_cal(request):
    target_id = request.ask['designId']
    rsp = RspMsg()
    try:
        root_path = os.path.join(STATIC_ROOT + '/business/user_params_file/')
        all_files = os.listdir(root_path)
        for item in all_files:
            if target_id in item:
                os.remove(os.path.join(root_path, item))
        CalResult.objects.filter(design_id=target_id).delete()
        DesignPlan.objects.filter(design_id=target_id).delete()
    except Exception as e:
        logger.exception("程序内部出现异常，请联系管理员")
        rsp.error(500, '程序内部出现异常，请联系管理员')
    return JsonResponse(rsp.get_result())


@require_POST
def get_device_data(request):
    device_type = request.ask['type']
    current_page = request.ask['currentPage']  # 当前页数
    current_size = request.ask['currentSize']  # 当前每页个数
    search_text = request.ask['searchText']

    rsp = RspMsg()
    from business.helper import page_n
    if device_type == "ice":
        target_device = ICE
    elif device_type == "gb":
        target_device = GasBoiler
    elif device_type == "eb":
        target_device = ElectricBoiler
    elif device_type == "ar":
        target_device = AR
    elif device_type == "iceTank":
        target_device = IceTank
    elif device_type == "eru":
        target_device = ERU
    elif device_type == "airPump":
        target_device = AirPump
    elif device_type == "gp":
        target_device = GroundPump
    elif device_type == "gt":
        target_device = GasTurbine
    elif device_type == "wp":
        target_device = WindPower
    elif device_type == "pvp":
        target_device = PVP
    elif device_type == "ars":
        target_device = ARS
    elif device_type == "buttery":
        target_device = Buttery
    else:
        logger.error("设备类型错误")
        rsp.error(500, "设备类型错误，请重新查找...")
        return JsonResponse(rsp.get_result())

    devices = target_device.objects.filter(model_name__contains=search_text).order_by('-is_default')
    device_info = page_n(devices, current_page, current_size)

    rsp.data = {
        'deviceList': [model_to_dict(i) for i in device_info.object_list],
        'paramsInfo': target_device.params_info(),
        'currentPage': current_page,
        'currentSize': current_size,
        'totalCount': devices.count()
    }
    return JsonResponse(rsp.get_result())


@require_POST
def update_device_info(request):
    device_id = request.ask['deviceId']
    device_type = request.ask['deviceType']
    is_change_default = request.ask['setDefault']

    rsp = RspMsg()
    if device_type == "ice":
        target_device = ICE
    elif device_type == "gb":
        target_device = GasBoiler
    elif device_type == "eb":
        target_device = ElectricBoiler
    elif device_type == "ar":
        target_device = AR
    elif device_type == "iceTank":
        target_device = IceTank
    elif device_type == "eru":
        target_device = ERU
    elif device_type == "airPump":
        target_device = AirPump
    elif device_type == "gp":
        target_device = GroundPump
    elif device_type == "gt":
        target_device = GasTurbine
    elif device_type == "wp":
        target_device = WindPower
    elif device_type == "pvp":
        target_device = PVP
    elif device_type == "ars":
        target_device = ARS
    elif device_type == "buttery":
        target_device = Buttery
    else:
        rsp.error(500, "设备类型错误，请重新查找...")
        return JsonResponse(rsp.get_result())

    if is_change_default:
        change_to = request.ask['changeTo']
        target_device.objects.filter(is_default=True).update(is_default=False)
        target_device.objects.filter(id=device_id).update(is_default=change_to)
    else:
        device_info = request.ask['devices']
        del device_info['id']  # id为自增，不需要修改
        del device_info['is_default']  # 职责单一，不允许在 is_change_default = false 的情况下修改默认设备
        target_device.objects.filter(id=device_id).update(**device_info)

    rsp.ok()
    return JsonResponse(rsp.get_result())


@require_POST
def add_devices(request):
    """
    添加设备方法
    """
    # 其次，获取参数中设备的类型
    device_type = request.ask['catalog']
    # 然后获取设备的名称
    device_info = request.ask['devices']
    model_name = device_info['model_name']

    rsp = RspMsg()
    # 这里判断参数中是否存在类别与设备名称
    # 获取设备名称的主要用途在于判断是否设备库中已经存在相同型号的设备
    # 如果存在，将不允许新增设备（设备型号在同类型下唯一）
    if (not device_type) or (not model_name):
        rsp.error(500, '请输入设备类型和设备型号')
        return JsonResponse(rsp.get_result())
    try:
        # 以内燃机为例：
        # 首先判断类别是否为内燃机
        # 其次查看数据库中是否存在设备名称
        # 如果以上均通过校验，则保存相应参数；如没有通过，则返回识别码501并提示'已存在该型号设备'
        if device_type == 'ice':
            # 内燃机
            if not ICE.objects.filter(model_name=model_name).exists():
                ICE(**device_info).save()
            else:
                rsp.error(501, '已存在该型号设备')
        elif device_type == 'gb':
            # 燃气锅炉
            if not GasBoiler.objects.filter(model_name=model_name).exists():
                GasBoiler(**device_info).save()
            else:
                rsp.error(501, '已存在该型号设备')
        elif device_type == 'eb':
            if not ElectricBoiler.objects.filter(model_name=model_name).exists():
                ElectricBoiler(**device_info).save()
            else:
                rsp.error(501, '已存在该型号设备')
        elif device_type == 'ar':
            if not AR.objects.filter(model_name=model_name).exists():
                AR(**device_info).save()
            else:
                rsp.error(501, '已存在该型号设备')
        elif device_type == 'iceTank':
            if not IceTank.objects.filter(model_name=model_name).exists():
                IceTank(**device_info).save()
            else:
                rsp.error(501, '已存在该型号设备')
        elif device_type == 'eru':
            if not ERU.objects.filter(model_name=model_name).exists():
                ERU(**device_info).save()
            else:
                rsp.error(501, '已存在该型号设备')
        elif device_type == 'airPump':
            if not AirPump.objects.filter(model_name=model_name).exists():
                AirPump(**device_info).save()
            else:
                rsp.error(501, '已存在该型号设备')
        elif device_type == 'gp':
            if not GroundPump.objects.filter(model_name=model_name).exists():
                GroundPump(**device_info).save()
            else:
                rsp.error(501, '已存在该型号设备')
        elif device_type == 'gt':
            if not GasTurbine.objects.filter(model_name=model_name).exists():
                GroundPump(**device_info).save()
            else:
                rsp.error(501, '已存在该型号设备')
        elif device_type == 'wp':
            if not WindPower.objects.filter(model_name=model_name).exists():
                WindPower(**device_info).save()
            else:
                rsp.error(501, '已存在该型号设备')
        elif device_type == 'pvp':
            if not PVP.objects.filter(model_name=model_name).exists():
                PVP(**device_info).save()
            else:
                rsp.error(501, '已存在该型号设备')
        elif device_type == 'ars':
            if not ARS.objects.filter(model_name=model_name).exists():
                ARS(**device_info).save()
            else:
                rsp.error(501, '已存在该型号设备')
        elif device_type == 'buttery':
            if not Buttery.objects.filter(model_name=model_name).exists():
                ARS(**device_info).save()
            else:
                rsp.error(501, '已存在该型号设备')
        else:
            raise ValueError()
    except Exception as e:
        logger.exception("存储错误，请检查设备类型和参数名称")
        rsp.error(500, '存储错误，请检查设备类型和参数名称')
    return JsonResponse(rsp.get_result())


@require_POST
def delete_devices(request):
    """
    删除设备方法
    """
    # 其次，获取参数中设备的类型
    device_type = request.ask['catalog']
    # 然后获取设备的名称
    which = request.ask['which']

    rsp = RspMsg()
    # 这里判断参数中是否存在类别与设备名称
    # 获取设备名称的主要用途在于判断是否设备库中已经存在相同型号的设备
    # 如果存在，将不允许新增设备（设备型号在同类型下唯一）
    if (not device_type) or (not which):
        rsp.error(500, '请输入设备类型和设备型号')
        return JsonResponse(rsp.get_result())

    if device_type == "ice":
        target_device = ICE
    elif device_type == "gb":
        target_device = GasBoiler
    elif device_type == "eb":
        target_device = ElectricBoiler
    elif device_type == "ar":
        target_device = AR
    elif device_type == "iceTank":
        target_device = IceTank
    elif device_type == "eru":
        target_device = ERU
    elif device_type == "airPump":
        target_device = AirPump
    elif device_type == "gp":
        target_device = GroundPump
    elif device_type == "gt":
        target_device = GasTurbine
    elif device_type == "wp":
        target_device = WindPower
    elif device_type == "pvp":
        target_device = PVP
    elif device_type == "ars":
        target_device = ARS
    elif device_type == "buttery":
        target_device = Buttery
    else:
        rsp.error(500, "设备类型错误，请重新查找...")
        return JsonResponse(rsp.get_result())

    target = target_device.objects.filter(id=which)
    if target.exists():
        target.delete()
    else:
        logger.error("该设备不存在")
        rsp.error(501, "该设备不存在")
    return JsonResponse(rsp.get_result())


@require_POST
def upload_params_file(request):
    """
    将用户下载后填写完成的负载文件，风资源，光资源文件进行保存：保存地址为：STATIC_ROOT + '/business/user_params_file/
    其中STATIC_ROOT为配置文件中定义的文件路径
    :param request:
    :return:
    """
    rsp = RspMsg()
    time_stamp = int(time.time())

    load_file = request.FILES.get("load_file", None)  # 获取上传的文件，如果没有文件，则默认为None
    wind_file = request.FILES.get("wind_file", None)  # 获取上传的文件，如果没有文件，则默认为None
    light_file = request.FILES.get("light_file", None)  # 获取上传的文件，如果没有文件，则默认为None

    who = request.POST.get("who", None)

    if not who:
        return redirect(reverse("Users:token_expired"))

    if not os.path.exists(STATIC_ROOT + '/business/user_params_file/'):
        os.mkdir(os.path.join(STATIC_ROOT + '/business/user_params_file/'))

    try:
        if load_file is None:
            rsp.error(500, '上传文件为空！')
            return JsonResponse(rsp.get_result())
        else:
            destination = open(
                os.path.join(STATIC_ROOT + '/business/user_params_file/', who + '_load_' + str(time_stamp) + '.xlsx'),
                'wb+')  # 打开特定的文件进行二进制的写操作
            for chunk in load_file.chunks():  # 分块写入文件
                destination.write(chunk)
            destination.close()

        if wind_file:
            destination = open(
                os.path.join(STATIC_ROOT + '/business/user_params_file/', who + '_wind_' + str(time_stamp) + '.xlsx'),
                'wb+')  # 打开特定的文件进行二进制的写操作
            for chunk in wind_file.chunks():  # 分块写入文件
                destination.write(chunk)
            destination.close()

        if light_file:
            destination = open(
                os.path.join(STATIC_ROOT + '/business/user_params_file/', who + '_light_' + str(time_stamp) + '.xlsx'),
                'wb+')  # 打开特定的文件进行二进制的写操作
            for chunk in light_file.chunks():  # 分块写入文件
                destination.write(chunk)
            destination.close()
    except Exception as e:
        logger.error("存储错误，请联系管理员")
        rsp.error(501, '存储错误，请联系管理员')
    else:
        rsp.data['mark'] = str(time_stamp)
    return JsonResponse(rsp.get_result())


@require_POST
def start_calculate(request):
    """
    进行规划的方法：
    :param request:
    :return:
    """
    rsp = RspMsg()
    token = request.ask['token']
    status, payload = auth.decode_token(token)
    who = auth.get_account(payload)
    mark = request.ask['mark']
    params = request.ask['params']
    economic_data = request.ask['economic']
    data_file = who + '_load_' + mark + '.xlsx'
    wind_file = who + '_wind_' + mark + '.xlsx'
    light_file = who + '_light_' + mark + '.xlsx'

    root_path = STATIC_ROOT + '/business/user_params_file/'
    # 首先会将配置规划的数据进行解析
    check_params = params
    # # 然后检查是否存在负载文件
    if os.path.exists(os.path.join(root_path, data_file)):
        rsp.msg = mark
    else:
        rsp.error(500, '负载文件异常，请联系管理员')
        return JsonResponse(rsp.get_result())
    # 然后校验是否配置中有风力选项，如果有则检查是否存在上传风资源文件
    if check_params['re']['wind']['is_selected'] == 1:
        if not os.path.exists(os.path.join(root_path, wind_file)):
            rsp.error(500, '未上传风机参数')
            return JsonResponse(rsp.get_result())
        else:
            wind_path = os.path.join(root_path, wind_file)

    # 类似的检查，用于校验是否存在光资源文件
    if check_params['re']['solar']['is_selected'] == 1:
        if not os.path.exists(os.path.join(root_path, light_file)):
            rsp.error(500, '未上传光伏设备参数')
            return JsonResponse(rsp.get_result())
        else:
            solar_path = os.path.join(root_path, light_file)

    # 如果通过以上校验，则将配置信息传入数据库中
    save_params(who, check_params, mark)

    # 由于计算极为耗时，所以此处开启线程进行处理，顺便将线程保存至全局变量中，方便获取计算进度
    cal_thread = CalThread(mark=mark, who=who, eco=economic_data)
    cal_thread.name = who + "_" + str(mark)
    cal_dict[cal_thread.name] = cal_thread
    cal_thread.start()
    # =====线程启动结束=========
    rsp.data = {"residual": float(check_params['algParams']['residual'])}
    return JsonResponse(rsp.get_result())


@require_POST
def get_calculate_schedule(request):
    """
    获取计算进度的方法，用于开始规划后，查看规划的进度
    :param request:
    :return:
    """
    token = request.ask['token']
    status, payload = auth.decode_token(token)
    who = auth.get_account(payload)
    mark = request.ask['mark']
    rsp = RspMsg()
    target_name = who + "_" + str(mark)

    all_live_thread = [i.name for i in threading.enumerate()]
    # rst = None
    if target_name in cal_dict.keys() and target_name in all_live_thread:
        rsp.code = 201
        rsp.data['schedule'], rsp.msg, rsp.data['curveData'] = cal_dict[target_name].get_result()
    elif target_name in cal_dict.keys() and target_name not in all_live_thread:
        is_wrong = CalResult.objects.filter(design_id=mark, is_correct=False).exists()
        if is_wrong:
            error_inf = 'Infeasible column'
            error_row_c = "Row 'constraint_c"
            error_row_c_explain = '【提示】未满足冷量平衡约束，请检查设备供冷出力是否与最大冷负荷匹配,并尝试提高供冷相关设备的限值'
            error_row_e = "Row 'constraint_e"
            error_row_e_explain = '【提示】未满足电平衡约束，请检查供电出力是否与最大电负荷匹配，并尝试提高供电相关设备的限值'
            error_row_h = "Row 'constraint_h"
            error_row_h_explain = '【提示】未满足热平衡约束，请检查设备供热出力是否与最大热负荷匹配，并尝试提高供热相关设备的限值'
            error_row_g = "Row 'constraint_g"
            error_row_g_explain = '【提示】请检查购气量是否满足气负荷与用气设备的总耗气量，并尝试提高气网供能上限'
            error_msg = CalResult.objects.values("error_msg").filter(design_id=mark, is_correct=False)[0]["error_msg"]
            if error_inf in error_msg:
                err_list = error_msg[error_msg.index(error_inf):error_msg.index("'.\nPresolve time")].split('_')
                error_msg = error_msg + '【提示】请检查第' + err_list[2] + '小时的供能是否满足该小时负荷,建议提高当前所选设备的限值'
            elif error_row_c in error_msg:
                error_msg = error_msg + error_row_c_explain
            elif error_row_h in error_msg:
                error_msg = error_msg + error_row_h_explain
            elif error_row_e in error_msg:
                error_msg = error_msg + error_row_e_explain
            elif error_row_g in error_msg:
                error_msg = error_msg + error_row_g_explain
            rsp.error(400, error_msg)
        else:
            rsp.msg = '已完成计算！'
        file_path = os.path.join(STATIC_ROOT + '/business/temp_log/', who + "_log_" + mark + ".log")
        if os.path.exists(file_path):
            os.remove(file_path)
    else:
        rsp.error(500, '无效的计算')
    return JsonResponse(rsp.get_result())


@require_POST
def get_supply_data(request):
    """
    将数据库中典型日的第一幅柱状图的数据返回给前端进行展示
    :param request:
    :return:
    """
    """展示供冷、供热的设备出力柱状图"""

    which_day = request.ask['which']  # 冬季、夏季
    which_plan = request.ask['which_plan']  # 方案id
    token = request.ask['token']
    status, payload = auth.decode_token(token)
    who = auth.get_account(payload)
    select_date = request.ask['selectDate']

    rsp = RspMsg()

    if which_day == "0":
        date = select_date if select_date else \
            DesignPlan.objects.values('winter_day').get(belongs__account=who, design_id=which_plan)['winter_day']
        # plan_date = DesignPlan.objects.values('winter_day').get(belongs__account=who, design_id=which_plan)
        data_target = CalResult.objects.values('gp_oh', 'cchp_oh', 'gb_oh', 'eb_oh', 'heat_buy', 'target_time',
                                               'heat_store', 'heat_release').filter(
            target_date=date, design_id=which_plan).order_by('-target_date')
        data_list = [
            [], [], [], [], [], [], []
        ]
        for i in data_target:
            data_list[0].append(int(i['gp_oh']))
            data_list[1].append(int(i['cchp_oh']))
            data_list[2].append(int(i['heat_buy']))
            data_list[3].append(int(i['eb_oh']))
            data_list[4].append(int(i['gb_oh']))
            data_list[5].append(int(i['heat_store']))
            data_list[6].append(int(i['heat_release']))
        rsp.data = data_list
    elif which_day == "1":
        date = select_date if select_date else DesignPlan.objects.values('summer_day').get(belongs__account=who,
                                                                                           design_id=which_plan)[
            'summer_day']
        data_target = CalResult.objects.values('gp_oc', 'ap_oc', 'cchp_oc', 'ar_oc', 'it_dis', 'it_ch', 'target_time',
                                               'eru_oc').filter(
            target_date=date,
            design_id=which_plan).order_by('-target_date')
        data_list = [
            [], [], [], [], [], []
        ]
        for i in data_target:
            data_list[0].append(i['gp_oc'])
            data_list[1].append(i['ap_oc'])
            data_list[2].append(i['cchp_oc'])
            data_list[3].append(i['ar_oc'])
            data_list[4].append(i['eru_oc'])
            data_list[5].append(i['it_dis'] if i['it_ch'] == 0 else - i['it_ch'])

        rsp.data = data_list
    else:
        rsp.error(500, '错误日期，请检查')
    return JsonResponse(rsp.get_result())


@require_POST
def get_load_data(request):
    """冷、热负荷折线图"""

    which_day = request.ask['which']  # 冬季、夏季
    which_plan = request.ask['which_plan']  # 方案id
    token = request.ask['token']
    status, payload = auth.decode_token(token)
    who = auth.get_account(payload)
    select_date = request.ask['selectDate']

    rsp = RspMsg()
    # plan_date = DesignPlan.objects.values('winter_day', 'summer_day').get(belongs__account=who, design_id=which_plan)

    if which_day == "0":
        date = select_date if select_date else \
            DesignPlan.objects.values('winter_day', 'summer_day').get(belongs__account=who, design_id=which_plan)[
                'winter_day']
        data_target = CalResult.objects.values('gp_oh', 'cchp_oh', 'eb_oh', 'heat_load', 'heat_buy',
                                               'heat_release', 'gb_oh').filter(target_date=date,
                                                                               design_id=which_plan).order_by(
            '-target_date')
        cal_data = [[], []]

        for i in data_target:
            cal_data[0].append(
                int(i['gp_oh'] + i['cchp_oh'] + i['eb_oh'] + i['heat_buy'] + i['heat_release'] + i['gb_oh']))
            cal_data[1].append(int(i['heat_load']))
        rsp.data = cal_data
    elif which_day == '1':
        date = select_date if select_date else \
            DesignPlan.objects.values('winter_day', 'summer_day').get(belongs__account=who, design_id=which_plan)[
                'summer_day']
        data_target = CalResult.objects.values('ar_oc', 'ap_oc', 'cchp_oc', 'gp_oc', 'it_dis', 'cold_load',
                                               'eru_oc').filter(
            target_date=date, design_id=which_plan).order_by('-target_date')
        cal_data = [[], []]

        for i in data_target:
            cal_data[0].append(int(i['ap_oc'] + i['cchp_oc'] + i['gp_oc'] + i['it_dis'] + i['ar_oc'] + i['eru_oc']))
            cal_data[1].append(int(i['cold_load']))

        rsp.data = cal_data
    else:
        rsp.error(500, '请求日期错误')
        return JsonResponse(rsp.get_result())

    return JsonResponse(rsp.get_result())


@require_POST
def get_power_data(request):
    """
    供电出力及耗电量柱状图
    :param request:
    :return:
    """

    which_day = request.ask['which']  # 冬季、夏季
    which_plan = request.ask['which_plan']  # 方案id
    token = request.ask['token']
    status, payload = auth.decode_token(token)
    who = auth.get_account(payload)
    select_date = request.ask['selectDate']

    rsp = RspMsg()
    # plan_date = DesignPlan.objects.values('winter_day', 'summer_day').get(belongs__account=who, design_id=which_plan)
    if which_day == "0":
        date = select_date if select_date else \
            DesignPlan.objects.values('winter_day', 'summer_day').get(belongs__account=who, design_id=which_plan)[
                'winter_day']
        data_target = CalResult.objects.values('ice_os', 'ele_buy', 'wind_power', 'pvp_power', 'gp_ieh', 'ap_ie',
                                               'eb_ie', 'it_ch',
                                               'ele_sell', 'ele_load', 'ele_ch', 'ele_dis', 'gp_iec').filter(
            target_date=date, design_id=which_plan).order_by('-target_date')
    elif which_day == '1':
        date = select_date if select_date else \
            DesignPlan.objects.values('winter_day', 'summer_day').get(belongs__account=who, design_id=which_plan)[
                'summer_day']
        data_target = CalResult.objects.values('ice_os', 'ele_buy', 'wind_power', 'pvp_power', 'gp_ieh', 'ap_ie',
                                               'eb_ie', 'it_ch',
                                               'ele_sell', 'ele_load', 'ele_ch', 'ele_dis', 'gp_iec').filter(
            target_date=date, design_id=which_plan).order_by('-target_date')
    else:
        rsp.error(500, '请求日期错误')
        return JsonResponse(rsp.get_result())

    rsp_data = []
    keys = ['ice_os', 'ele_buy', 'wind_power', 'pvp_power', 'gp_ieh', 'ap_ie', 'eb_ie', 'it_ch',
            'ele_sell', 'ele_load', 'ele_ch', 'ele_dis', 'gp_iec']
    for i in range(len(keys)):
        rsp_data.append([])

    for i in data_target:
        for index, item in enumerate(keys):
            coe = -1 if index > 3 and index != 11 else 1
            rsp_data[index].append(int(coe * i[item]))

    rsp.data = rsp_data
    return JsonResponse(rsp.get_result())


@require_POST
def get_power_sum(request):
    """对比供冷、供热的出力"""

    which_day = request.ask['which']  # 冬季、夏季
    which_plan = request.ask['which_plan']  # 方案id
    token = request.ask['token']
    status, payload = auth.decode_token(token)
    who = auth.get_account(payload)
    select_date = request.ask['selectDate']
    rsp = RspMsg()

    sum_data = CalResult.objects.values('ele_buy', 'ice_os', 'wind_power', 'pvp_power', 'gp_ieh', 'gp_iec', 'ap_ie',
                                        'it_ch', 'ele_sell', 'eb_ie',
                                        'ele_load', 'eru_ie', 'ele_dis', 'ele_ch')
    if which_day == "0":
        date = select_date if select_date else \
            DesignPlan.objects.values('winter_day', 'summer_day').get(belongs__account=who, design_id=which_plan)[
                'winter_day']
        data_target = sum_data.filter(target_date=date, design_id=which_plan).order_by(
            '-target_date')
    elif which_day == '1':
        date = select_date if select_date else \
            DesignPlan.objects.values('winter_day', 'summer_day').get(belongs__account=who, design_id=which_plan)[
                'summer_day']
        data_target = sum_data.filter(target_date=date, design_id=which_plan).order_by(
            '-target_date')
    else:
        rsp.error(500, '请求日期错误')
        return JsonResponse(rsp.get_result())

    cal_data = [[], []]
    for i in data_target:
        cal_data[0].append(int(i['ele_buy'] + i['ice_os'] + i['wind_power'] + i['pvp_power'] + i['ele_dis']))
        cal_data[1].append(int(i['gp_ieh'] + i['gp_iec'] + i['ap_ie'] + i['eb_ie'] +
                               i['eru_ie'] + i['ele_sell'] + i['ele_load'] + i['ele_ch']))

    rsp.data = cal_data
    return JsonResponse(rsp.get_result())


@require_POST
def show_temp_day(request):
    """
    用于处理典型日中的相关数据，通过获取数据库中的历史结果，进行汇总统计后返回给前端展示
    :param request:
    :return:
    """

    which_plan = request.ask['which_plan']  # 方案id
    token = request.ask['token']
    summer = winter = None
    if "summer" in request.ask.keys():
        summer = request.ask['summer']
    if "winter" in request.ask.keys():
        winter = request.ask['winter']

    status, payload = auth.decode_token(token)
    who = auth.get_account(payload)

    rsp = RspMsg()

    if not which_plan:
        design = DesignPlan.objects.filter(belongs__account=who).order_by('-design_id')[0].design_id
    try:
        design = DesignPlan.objects.values('summer_day', 'winter_day', 'gt_which',
                                           'ice_which', 'gp_which', 'ap_which', 'gb_which', 'ar_which', 'eb_which',
                                           'cu_which',
                                           'wind_which', 'solar_which').get(belongs__account=who, design_id=which_plan)
    except Exception as e:
        logger.error("数据库查询错误，请联系管理员")
        rsp.error(500, '数据库查询错误，请联系管理员')
        return HttpResponse(rsp.get_result())

    table_head = ['日期', '时间', 'CCHP发电', 'GSHP供热', 'GSHP供冷', 'ACHP供冷', 'GB供热',
                  'AR供冷', 'EB供热', '冰蓄冷', '购电量', '购电费', '购气量', '购气费', '购热量', '购热费', '售电',
                  '售电收入', '风机', '光伏板', 'CCHP供热', 'CCHP供冷']

    all_data = CalResult.objects.filter(design_id=which_plan)
    config_res = ConfigLimit.objects.filter(design_id=which_plan)

    winter_day = all_data.filter(target_date=winter if winter else design['winter_day'])
    summer_day = all_data.filter(target_date=summer if summer else design['summer_day'])

    # 首先定义汇总信息的保存变量
    summary = {}
    # 其次，通过聚合函数获取到数据库中已经计算好的结果的求和信息
    sum_data = all_data.aggregate(ele_buy=Sum('ele_buy'), gas_buy=Sum('gas_buy'),
                                  heat_buy=Sum('heat_buy'),
                                  wind_power=Sum('wind_power'), pvp_power=Sum('pvp_power'),
                                  sell_e=Sum('sell_e'),
                                  sell_h=Sum('sell_h'), sell_c=Sum('sell_c'),
                                  ele_inc=Sum('ele_inc'),
                                  heat_load=Sum('heat_load'),
                                  cold_load=Sum('cold_load'), ele_load=Sum('ele_load'),
                                  ele_sell=Sum('ele_sell'), ele_pri=Sum('ele_pri'),
                                  gas_pri=Sum('gas_pri'),
                                  heat_pri=Sum('heat_pri'), ice_os=Sum('ice_os'),
                                  gp_ieh=Max('gp_ieh'),
                                  ap_ie=Max('ap_ie'), gb_ig=Max('gb_ig'), ar_ig=Max('ar_ig'),
                                  eb_ie=Max('eb_ie'), eru=Max('it_ch'),
                                  co2_em=Sum('co2_em'),
                                  nox_em=Sum('nox_em'))

    for (k, v) in sum_data.items():
        if v is None:
            sum_data[k] = 0
    summary['co2_em'] = sum_data['co2_em'] / 1000 if sum_data['co2_em'] else 0  # 二氧化碳排放
    summary['nox_em'] = sum_data['nox_em'] / 1000 if sum_data['nox_em'] else 0  # 氮氧化物排放

    summary['energy_cons'] = (sum_data['ele_buy'] + sum_data['gas_buy'] + sum_data['heat_buy']) / 1000  # 一次能耗

    summary['e_eff'] = 0 if summary['energy_cons'] == 0 else ((sum_data['heat_load'] + sum_data['cold_load'] + sum_data[
        'ele_load'] +
                                                               sum_data['ele_sell']) / 10) / summary[
                                                                 'energy_cons']  # 能源利用率

    summary['ce_generation'] = 0 if (sum_data['wind_power'] + sum_data['pvp_power']) == 0 else \
        100 * (sum_data['wind_power'] + sum_data['pvp_power']) / (
                sum_data['ele_buy'] + sum_data['wind_power'] + sum_data['pvp_power'] + sum_data['ice_os'])  # 清洁能源发电占比

    summary['income'] = (sum_data['sell_e'] + sum_data['sell_h'] + sum_data['sell_c'] + sum_data['ele_inc']) / 10000

    summary['fuel'] = (sum_data['ele_pri'] + sum_data['gas_pri'] + sum_data['heat_pri']) / 10000

    cal_data = CalResult.objects.filter(design_id=which_plan).aggregate(wind=Max('wind'), pvp=Max('PV'),
                                                                        cchp=Max('ice_os'), gp=Max('gp_oh'),
                                                                        ap=Max('ap_oc'), gb=Max('gb_oh'),
                                                                        ar=Max('ar_oc'),
                                                                        eb=Max('eb_oh'), eru=Max('eru_oc'))
    if design['gt_which'] and not design['ice_which']:
        ccph_pri = GasTurbine.objects.get(model_name=design['gt_which']).ppp * cal_data['cchp']
    elif not design['gt_which'] and design['ice_which']:
        ccph_pri = ICE.objects.get(model_name=design['ice_which']).ppp * cal_data['cchp']
    else:
        ccph_pri = 0

    if design['gp_which']:
        gp_pri = GroundPump.objects.get(model_name=design['gp_which']).ppp * cal_data['gp']
    else:
        gp_pri = 0

    if design['ap_which']:
        ap_pri = AirPump.objects.get(model_name=design['ap_which']).ppp * cal_data['ap']
    else:
        ap_pri = 0

    if design['gb_which']:
        gb_pri = GasBoiler.objects.get(model_name=design['gb_which']).ppp * cal_data['gb']
    else:
        gb_pri = 0

    if design['ar_which']:
        ar_pri = AR.objects.get(model_name=design['ar_which']).ppp * cal_data['ar']
    else:
        ar_pri = 0

    if design['eb_which']:
        eb_pri = ElectricBoiler.objects.get(model_name=design['eb_which']).ppp * cal_data['eb']
    else:
        eb_pri = 0

    if design['cu_which']:
        eru_pri = ERU.objects.get(model_name=design['cu_which']).ppp * cal_data['eru']
    else:
        eru_pri = 0

    if design['wind_which']:
        wind_pri = WindPower.objects.get(model_name=design['wind_which']).ppp * cal_data['wind']
    else:
        wind_pri = 0

    if design['solar_which']:
        pvp_pri = PVP.objects.get(model_name=design['solar_which']).ppp * cal_data['pvp']
    else:
        pvp_pri = 0

    battery_ppu = 0
    if design.__contains__("battery_which"):
        if design['battery_which']:
            battery_ppu = Buttery.objects.get(model_name=design['battery_which']).ppu
        else:
            battery_ppu = Buttery.objects.get(is_default=True).ppu

    v = 0
    i = 0.07
    R = (i * ((1 + i) ** 20)) / (((1 + i) ** 20) - 1)
    summary['invest'] = (R * (1 - v) + i * v) * ((ccph_pri + gp_pri + ap_pri + gb_pri + ar_pri +
                                                  eb_pri + eru_pri + pvp_pri + battery_ppu) + wind_pri) / 10000

    summary['opration'] = summary['invest'] * 0.17

    summary['year_of_system'] = summary['income'] - (summary['invest'] + summary['opration'] + summary['fuel'])

    from django.core import serializers

    result = {'table_head': table_head, "winter_day": serializers.serialize("json", winter_day),
              "summer_day": serializers.serialize("json", summer_day),
              'which': which_plan,
              'summary': summary}
    rsp.data = result
    return JsonResponse(rsp.get_result())


@require_POST
def opt_cal(request):
    rsp = RspMsg()
    time_stamp = int(time.time())
    load_file = request.FILES.get("opt_load_file", None)  # 获取上传的文件，如果没有文件，则默认为None
    info = request.POST.get("optConfig", None)
    who = request.POST.get("who", None)

    if not who:
        return redirect(reverse("Users:token_expired"))

    if not info:
        rsp.error(501, '配置信息为空，请检查')
        return JsonResponse(rsp.get_result())

    if not os.path.exists(STATIC_ROOT + '/business/user_params_file/'):
        os.mkdir(os.path.join(STATIC_ROOT + '/business/user_params_file/'))

    try:
        if load_file is None:
            rsp.error(500, '上传文件为空！')
            return JsonResponse(rsp.get_result())
        else:
            destination = open(
                os.path.join(STATIC_ROOT + '/business/user_params_file/',
                             who + '_opt_load_' + str(time_stamp) + '.xlsx'),
                'wb+')  # 打开特定的文件进行二进制的写操作
            for chunk in load_file.chunks():  # 分块写入文件
                destination.write(chunk)
            destination.close()

        info = json.loads(info)
        helper.save_opt_params(who, info, time_stamp)
        opt_thread = OptThread(who, time_stamp)
        opt_thread.name = who + "_" + str(time_stamp)
        opt_dict[opt_thread.name] = opt_thread
        opt_thread.start()
        rsp.data["mark"] = str(time_stamp)
    except Exception as e:
        print("error------>", str(e))
        logger.error("计算过程错误")
        rsp.error('501', "计算过程错误，请检查配置数据等相关参数...")
    return JsonResponse(rsp.get_result())


@require_POST
def get_opt_progress(request):
    token = request.ask['token']
    status, payload = auth.decode_token(token)
    who = auth.get_account(payload)
    mark = request.ask['mark']
    rsp = RspMsg()
    target_name = who + "_" + str(mark)
    all_live_thread = [i.name for i in threading.enumerate()]
    # rst = None
    if target_name in opt_dict.keys() and target_name in all_live_thread:
        rsp.code = 201
        rsp.data['schedule'], rsp.msg = opt_dict[target_name].get_result()
        print('schedule--->' + str(rsp.data['schedule']))
    elif target_name in opt_dict.keys() and target_name not in all_live_thread:
        rsp.msg = '已完成计算！'
    else:
        rsp.error(500, '无效的计算')
    return JsonResponse(rsp.get_result())


@require_POST
def get_opt_history(request):
    token = request.ask['token']
    status, payload = auth.decode_token(token)
    who = auth.get_account(payload)

    search = request.ask['searchText']
    current_page = request.ask["currentPage"]
    current_size = request.ask["currentSize"]
    all_opt = OptConfig.objects.order_by('-opt_id').values("opt_id", "opt_name", 'opt_desc', 'predict_date',
                                                           'time').filter(belongs__account=who,
                                                                          opt_name__contains=search)

    opt_list = list(page_n(all_opt, current_page, current_size))
    rsp = RspMsg()
    rsp.code = 200
    rsp.data = {
        "optList": opt_list,
        'currentPage': current_page,
        'currentSize': current_size,
        'totalCount': all_opt.count()
    }
    return JsonResponse(rsp.get_result())


@require_POST
def delete_item_opt(request):
    token = request.ask['token']
    status, payload = auth.decode_token(token)
    who = auth.get_account(payload)
    which = request.ask['which']
    try:
        rsp = RspMsg()
        target_result = OptResult.objects.filter(opt_id=which)
        target_config = OptConfig.objects.filter(opt_id=which, belongs__account=who)
        target_config.delete()
        target_result.delete()
        rsp.ok()
    except Exception as e:
        logger.exception("删除失败，请联系管理员")
        rsp.error(500, '删除失败，请联系管理员')
    finally:
        return JsonResponse(rsp.get_result())


@require_POST
def get_plan_output_table(request):
    # token = request.ask['token']
    # status, payload = auth.decode_token(token)
    # who = auth.get_account(payload)
    which = request.ask['which']

    table_data = OptResult.objects.values("target_time", "ice_os", "gp_oh", "gp_oc", "ap_oc", "gb_oh", "ar_oc", "eb_oh",
                                          "ice_store",
                                          "ele_buy", "ele_pri", "gas_buy", "gas_pri", "heat_buy", "heat_pri",
                                          "ele_sell", "ele_inc", "wind", "PV", "cchp_oh", 'cchp_oc').filter(
        opt_id=which).order_by("target_time")
    rsp = RspMsg()
    rsp.data["table_data"] = list(table_data)
    return JsonResponse(rsp.get_result())


@require_POST
def get_sub_option_graph(request):
    which = request.ask["which"]
    energy_type = request.ask['type']

    graph_data = None
    if energy_type == "elect":
        search_data = OptResult.objects.filter(opt_id=which).values("ice_os", "ele_buy", "wind_power", "pvp_power",
                                                                    "heat_store", "heat_release")
        graph_data = [
            {
                "name": "CCHP发电",
                "type": "bar",
                "stack": "总量",
                "data": []
            },
            {
                "name": "购电量",
                "type": "bar",
                "stack": "总量",
                "data": []
            },
            {
                "name": "风电",
                "type": "bar",
                "stack": "总量",
                "data": []
            },
            {
                "name": "光电",
                "type": "bar",
                "stack": "总量",
                "data": []
            },
            {
                "name": "充电",
                "type": "bar",
                "stack": "总量",
                "data": []
            },
            {
                "name": "放电",
                "type": "bar",
                "stack": "总量",
                "data": []
            },

        ]
        for i in search_data:
            graph_data[0]['data'].append(int(i["ice_os"]))
            graph_data[1]['data'].append(int(i["ele_buy"]))
            graph_data[2]['data'].append(int(i["wind_power"]))
            graph_data[3]['data'].append(int(i["pvp_power"]))
            graph_data[4]['data'].append(int(i["ele_ch"]))
            graph_data[5]['data'].append(int(i["ele_dis"]))
    elif energy_type == 'gas':
        search_data = OptResult.objects.filter(opt_id=which).values('gas_buy')
        graph_data = [
            {
                "name": "购气",
                "type": "bar",
                "stack": "总量",
                "data": []
            },
        ]
        for i in search_data:
            graph_data[0]['data'].append(i["gas_buy"])
    elif energy_type == 'heat':
        search_data = OptResult.objects.filter(opt_id=which).values('gp_oh', 'cchp_oh', 'gb_oh', 'eb_oh', 'heat_buy',
                                                                    'heat_store', 'heat_release')
        graph_data = [
            {
                "name": "地源热泵",
                "type": "bar",
                "stack": "总量",
                "data": []
            },
            {
                "name": "CCHP",
                "type": "bar",
                "stack": "总量",
                "data": []
            },
            {
                "name": "燃气锅炉",
                "type": "bar",
                "stack": "总量",
                "data": []
            },
            {
                "name": "电锅炉",
                "type": "bar",
                "stack": "总量",
                "data": []
            }, {
                "name": "热网",
                "type": "bar",
                "stack": "总量",
                "data": []
            },
            {
                "name": "储热",
                "type": "bar",
                "stack": "总量",
                "data": []
            },
            {
                "name": "放热",
                "type": "bar",
                "stack": "总量",
                "data": []
            },
        ]
        for i in search_data:
            graph_data[0]['data'].append(int(i["gp_oh"]))
            graph_data[1]['data'].append(int(i["cchp_oh"]))
            graph_data[2]['data'].append(int(i["gb_oh"]))
            graph_data[3]['data'].append(int(i["eb_oh"]))
            graph_data[4]['data'].append(int(i["heat_buy"]))
    elif energy_type == 'cold':
        search_data = OptResult.objects.filter(opt_id=which).values('ap_oc', 'cchp_oc', 'ar_oc', 'gp_oc', 'ice_store',
                                                                    'it_dis')
        graph_data = [
            {
                "name": "风冷热泵",
                "type": "bar",
                "stack": "总量",
                "data": []
            },
            {
                "name": "CCHP",
                "type": "bar",
                "stack": "总量",
                "data": []
            },
            {
                "name": "吸收式制冷机",
                "type": "bar",
                "stack": "总量",
                "data": []
            },
            {
                "name": "地源热泵",
                "type": "bar",
                "stack": "总量",
                "data": []
            }, {
                "name": "冰蓄冷",
                "type": "bar",
                "stack": "总量",
                "data": []
            },
            {
                "name": "冷水机组",
                "type": "bar",
                "stack": "总量",
                "data": []
            },
        ]
        for i in search_data:
            graph_data[0]['data'].append(int(i["ap_oc"]))
            graph_data[1]['data'].append(int(i["cchp_oc"]))
            graph_data[2]['data'].append(int(i["ar_oc"]))
            graph_data[3]['data'].append(int(i["gp_oc"]))
            graph_data[4]['data'].append(int(i["ice_store"]))
            graph_data[5]['data'].append(int(i["it_dis"]))

    rsp = RspMsg()
    rsp.data["graph_data"] = graph_data
    return JsonResponse(rsp.get_result())


@require_POST
def get_opt_overview(request):
    rsp = RspMsg()
    opt_id = request.ask["optId"]

    target_rst = OptResult.objects.values().filter(opt_id=opt_id)
    if target_rst.exists():
        rsp.data['isCorrect'] = True
        all_table_data = DataFrame(list(target_rst))
        sum_ele_buy = all_table_data.ele_buy.sum()  # 购电量
        sum_ele_pri = all_table_data.ele_pri.sum()  # 购电费用
        sum_gas_buy = all_table_data.gas_buy.sum()  # 购气量
        sum_gas_pri = all_table_data.gas_pri.sum()  # 购气费用
        sum_heat_buy = all_table_data.heat_buy.sum()  # 购热量
        sum_heat_pri = all_table_data.heat_pri.sum()  # 购热费用
        fuel = sum_ele_pri + sum_gas_pri + sum_heat_pri  # 燃料动力成本
        cons = sum_ele_buy + sum_gas_buy + sum_heat_buy  # 一次能耗
        income = (all_table_data.sell_h + all_table_data.sell_c.sum() + all_table_data.sell_e.sum()).sum()  # 营业收入
        # 清洁能源发电占比
        clean_energy = (all_table_data.wind_power + all_table_data.pvp_power).sum() / all_table_data.sell_e.sum()
        rsp.data['summaryData'] = {}
        rsp.data['summaryData']['buy_elect'] = sum_ele_buy
        rsp.data['summaryData']['buy_elect_cost'] = sum_ele_pri / 10000
        rsp.data['summaryData']['buy_gas'] = sum_gas_buy
        rsp.data['summaryData']['buy_gas_cost'] = sum_gas_pri / 10000
        rsp.data['summaryData']['buy_heat'] = sum_heat_buy
        rsp.data['summaryData']['buy_heat_cost'] = sum_heat_pri / 10000
        rsp.data['summaryData']['fuel'] = fuel / 10000
        rsp.data['summaryData']['cons'] = cons
        rsp.data['summaryData']['income'] = income / 10000
        rsp.data['summaryData']['clean_energy'] = clean_energy
    else:
        rsp.data['isCorrect'] = False
    return JsonResponse(rsp.get_result())


@require_POST
def get_opt_table_rst(request):
    rsp = RspMsg()
    opt_id = request.ask["optId"]

    target_rst = OptResult.objects.values().filter(opt_id=opt_id)
    if target_rst.exists():
        rsp.data['isCorrect'] = True
        rsp.data['winterTableData'] = list(target_rst)
    else:
        rsp.data['isCorrect'] = False
    return JsonResponse(rsp.get_result())


@require_POST
def get_opt_graph_rst(request):
    rsp = RspMsg()
    opt_id = request.ask["optId"]
    graph_num = request.ask["graphNum"]

    target_rst = OptResult.objects.values().filter(opt_id=opt_id)
    if target_rst.exists():
        rsp.data['isCorrect'] = True
        all_table_data = DataFrame(list(target_rst))
        rsp.data['winterTableData'] = list(get_graph_data(graph_num, all_table_data))
    else:
        rsp.data['isCorrect'] = False
    return JsonResponse(rsp.get_result())


def get_graph_data(graph_num, all_table_data: DataFrame):
    gp_heat = all_table_data.gp_oh.values
    cchp_heat = all_table_data.cchp_oh.values
    heat_buy = all_table_data.heat_buy.values
    eb_heat = all_table_data.eb_oh.values
    gb_heat = all_table_data.gb_oh.values
    heat_ch = -all_table_data.heat_store.values
    heat_dis = all_table_data.heat_release.values
    gp_c = all_table_data.gp_oc.values
    ap_c = all_table_data.ap_oc.values
    cchp_c = all_table_data.cchp_oc.values
    ar_c = all_table_data.ar_oc.values
    eru_c = all_table_data.eru_c.values
    c_ch = all_table_data.ice_store.values
    c_dis = all_table_data.ice_dis.values
    ele_buy = all_table_data.ele_buy.values
    cchp_ele = all_table_data.ice_os.values
    wind_power = all_table_data.wind_power.values
    pvp_power = all_table_data.pvp_power.values
    gp_ele = all_table_data.gp_ieh.values
    ap_ele = all_table_data.ap_ie.values
    eb_ele = all_table_data.eb_ie.values
    eru_ele = all_table_data.eru_ele.values
    sell_ele = all_table_data.ele_sell.values
    ele_load = all_table_data.ele_load.values
    ele_ch = all_table_data.ele_ch.values
    ele_dis = all_table_data.ele_dis.values
    result = []
    if graph_num == 0:
        result = [gp_heat, cchp_heat, heat_buy, eb_heat, gb_heat, - heat_ch, heat_dis]
    elif graph_num == 1:
        heat_load = all_table_data.heat_load.values
        heat_sup = gp_heat + cchp_heat + heat_buy + eb_heat + gb_heat + heat_dis
        result = [list(heat_load), list(heat_sup)]
    elif graph_num == 2:
        result = [gp_c, ap_c, cchp_c, ar_c, eru_c, - c_ch, c_dis]
    elif graph_num == 3:
        c_load = all_table_data.cold_load
        c_sup = gp_c + ap_c + cchp_c + ar_c + eru_c + c_dis
        result = [c_load, c_sup]
    elif graph_num == 4:
        result = [ele_buy, cchp_ele, wind_power, pvp_power, - gp_ele, - ap_ele, - eb_ele, - eru_ele, - sell_ele,
                  -ele_load,
                  - ele_ch, ele_dis]
    elif graph_num == 5:
        ele_load = all_table_data.ele_load.values
        ele_sup = ele_buy + cchp_c + pvp_power + wind_power
        ele_cons = eb_ele + eru_ele + gp_ele + ap_ele + ele_ch
        result = [ele_load + ele_cons, ele_sup]

    rst = map(lambda x: list(x), result)
    return rst


def test(request):
    which = "winter_day"
    print(DesignPlan.objects.values().first()[which])
    return HttpResponse("ok")
